<?php
/**
 * Schema for MySQL databases
 *
 * @author André Silva
 */
class MysqlSchema implements ISchema {
	private $schema;

	function __construct($schema = '') {
		$this->schema = $schema;
	}

	/**
	 * Retorna uma lista de campos do Criteria
	 * @param Criteria $criteria
	 * @return array
	 */
	private function getColumns($criteria) {
		$annotation = $criteria->getAnnotation();
		$all = array_merge($annotation['columns'], $annotation['joinColumns']);
		$columns = $criteria->getSelect();

		if (!empty ($columns)) {
			$columns = explode(',', $columns);
		} else {
			$columns = $all;
		}
		$columns = array_intersect($all, $columns);
		$columns = array_unique($columns);
		return $columns;
	}

	/**
	 * Gera um comando SQL baseado em um critério
	 *
	 * @param Criteria $criteria
	 * @return string
	 */
	public function generateSelect($criteria) {
		$table   = $criteria->getTable();

		$columns = $criteria->getSelect();
		$where   = $criteria->getWhere();
		$order   = $criteria->getOrderby();
		$group   = $criteria->getGroupby();
		$offset  = $criteria->getOffset();
		$limit   = $criteria->getLimit();

		$columns = empty($columns) ? $table.'.*' : $columns;
		$where   = empty($where)   ? ''  : 'WHERE ' . $where;
		$order   = empty($order)   ? ''  : 'ORDER BY ' . $order;
		$group   = empty($group)   ? ''  : 'GROUP BY ' . $group;
		$offset  = empty($offset)  ? ''  : 'OFFSET ' . $offset;
		$limit   = empty($limit)   ? ''  : 'LIMIT ' . $limit;

		$joins = '';
		foreach ($criteria->getJoins() as $join) {
			$joins .= ' JOIN ' . $join['name'] . ' ON ( ' . $table.'.'.$criteria->getPrimaryKey() . '='.$join['name'].'.'.$join['joinColumn'].')';
		}

		return "SELECT $columns FROM $table $joins $where $group $order $limit $offset";
	}

	/**
	 * Gera um comando SQL baseado em um critério
	 *
	 * @param Criteria $criteria
	 * @return string
	 */
	public function generateDelete($criteria) {
		$table   = $criteria->getTable();

		$where   = $criteria->getWhere();
		$offset  = $criteria->getOffset();
		$limit   = $criteria->getLimit();

		$where   = empty($where)   ? ''  : 'WHERE ' . $where;
		$offset  = empty($offset)  ? ''  : 'OFFSET ' . $offset;
		$limit   = empty($limit)   ? ''  : 'LIMIT ' . $limit;

		return "DELETE FROM $table $where $limit $offset";
	}

	/**
	 * Gera um comando SQL INSERT baseado em um critério e objeto
	 *
	 * @param Criteria $criteria
	 * @param Bean $bean
	 * @return string
	 */
	public function generateInsert($criteria, $bean, $forcePrimary = false) {
		$annotation = $criteria->getAnnotation();
		$table = $criteria->getTable();
		$columns = $this->getColumns($criteria);

		$properties = array();
		$values = array();

		foreach ($columns as $property) {
			if ($bean->$property === null || (!$forcePrimary && $property == $criteria->getPrimaryKey())) {
				continue;
			}

			array_push($properties, '`'.$property.'`');
			$get = 'get'.ucfirst($property);
			array_push($values, Criteria::formatToSQL($bean->$get(), $annotation['properties'][$property]['var']));
		}

		$properties = implode(',', $properties);
		$values = implode(',', $values);
		return "INSERT INTO `$table` ($properties) VALUES ($values)";
	}

	/**
	 * Gera um comando SQL UPDATE baseado em um critério e objeto
	 *
	 * @param Criteria $criteria
	 * @param Bean $bean
	 * @return string
	 */
	public function generateUpdate($criteria, $bean) {
		$annotation = Annotation::getClassAnnotation($criteria->getClassname());
		$table   = $criteria->getTable();
		$columns = $this->getColumns($criteria);
		$where = 'WHERE '.$criteria->getWhere();

		$properties = array();

		foreach ($columns as $property) {
			if ($bean->$property === null || $property == $criteria->getPrimaryKey()) {
				continue;
			}

			array_push($properties, $property . ' = ' . Criteria::formatToSQL($bean->$property, $annotation['properties'][$property]['var']));
		}

		$properties = implode(',', $properties);
		return "UPDATE $table SET $properties $where";
	}

	public function getDateFormat() {
		return '%Y-%m-%d';
	}
}
?>
